{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Stock Market Tracker - Latest Market Movers Dashboard\n",
    "\n",
    "This notebook demonstrates an autonomous research agent that:\n",
    "- Fetches latest stock market news and data\n",
    "- Identifies stocks that rose and fell today\n",
    "- Creates a beautiful HTML dashboard with market analysis\n",
    "\n",
    "## Requirements\n",
    "\n",
    "1. **API Keys** (set in `.env` file):\n",
    "   - `ANTHROPIC_API_KEY` - Get from https://console.anthropic.com/\n",
    "\n",
    "2. **MCP Servers** (install if needed):\n",
    "   ```bash\n",
    "   # Fetch server for web research\n",
    "   pip install mcp-server-fetch\n",
    "   \n",
    "   # Filesystem server for saving HTML\n",
    "   npm install -g @modelcontextprotocol/server-filesystem\n",
    "   ```\n",
    "\n",
    "3. **Python Packages**:\n",
    "   ```bash\n",
    "   pip install 'aisuite[anthropic,mcp]' python-dotenv\n",
    "   ```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✓ Environment configured\n",
      "✓ Working directory: /Users/rohit/fleet/leclerc/aisuite-prs/aisuite-main/aisuite/examples/agents\n",
      "✓ Today's date: 2025-11-10\n",
      "\n",
      "Ready to track the markets!\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import json\n",
    "from pathlib import Path\n",
    "from dotenv import load_dotenv\n",
    "from datetime import datetime\n",
    "import aisuite as ai\n",
    "from aisuite.mcp import MCPClient\n",
    "\n",
    "# Load environment variables\n",
    "load_dotenv()\n",
    "\n",
    "# Verify required API keys\n",
    "if not os.getenv(\"ANTHROPIC_API_KEY\"):\n",
    "    raise ValueError(\n",
    "        \"Missing ANTHROPIC_API_KEY\\n\"\n",
    "        \"Please add it to your .env file\"\n",
    "    )\n",
    "\n",
    "print(\"✓ Environment configured\")\n",
    "print(f\"✓ Working directory: {os.getcwd()}\")\n",
    "print(f\"✓ Today's date: {datetime.now().strftime('%Y-%m-%d')}\")\n",
    "print(\"\\nReady to track the markets!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize MCP Servers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✓ MCP servers initialized\n",
      "\n",
      "Available tools:\n",
      "  - Fetch: ['fetch']\n",
      "  - Filesystem: ['read_file', 'read_text_file', 'read_media_file', 'read_multiple_files', 'write_file', 'edit_file', 'create_directory', 'list_directory', 'list_directory_with_sizes', 'directory_tree', 'move_file', 'search_files', 'get_file_info', 'list_allowed_directories']\n"
     ]
    }
   ],
   "source": [
    "# Fetch MCP Server - for web research\n",
    "fetch_mcp = MCPClient(\n",
    "    command=\"uvx\",\n",
    "    args=[\"mcp-server-fetch\"],\n",
    "    name=\"fetch\"\n",
    ")\n",
    "\n",
    "# Filesystem MCP Server - for saving HTML files\n",
    "filesystem_mcp = MCPClient(\n",
    "    command=\"npx\",\n",
    "    args=[\"-y\", \"@modelcontextprotocol/server-filesystem\", os.getcwd()],\n",
    "    name=\"filesystem\"\n",
    ")\n",
    "\n",
    "print(\"✓ MCP servers initialized\")\n",
    "print(f\"\\nAvailable tools:\")\n",
    "print(f\"  - Fetch: {[tool['name'] for tool in fetch_mcp.list_tools()]}\")\n",
    "print(f\"  - Filesystem: {[tool['name'] for tool in filesystem_mcp.list_tools()]}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Generate Market Movers Dashboard\n",
    "\n",
    "Watch the AI agent:\n",
    "1. Fetch latest stock market news and data\n",
    "2. Identify top gainers and losers\n",
    "3. Create a comprehensive HTML dashboard\n",
    "4. **Save the HTML file FIRST** (critical!)\n",
    "5. Provide summary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "📈 Fetching latest stock market data...\n",
      "\n",
      "============================================================\n",
      "\n",
      "============================================================\n",
      "✓ STOCK MARKET DASHBOARD COMPLETE!\n",
      "============================================================\n",
      "\n",
      "The stock market dashboard for November 10, 2025, has been successfully created and saved as 'stock_market_dashboard.html'. Here's a summary of the dashboard:\n",
      "\n",
      "- **Number of Stocks Analyzed**: Multiple stocks, focusing on the top 3 gainers.\n",
      "- **Top 3 Gainers**:\n",
      "  1. **Cogent Biosciences, Inc. (COGT)**: Price $32.46, Change +119.03%\n",
      "  2. **Navitas Semiconductor Corporation (NVTS)**: Price $9.60, Change +22.45%\n",
      "  3. **Opendoor Technologies Inc. (OPEN)**: Price $7.99, Change +21.77%\n",
      "- **Overall Market Sentiment**: Bullish\n",
      "- **Key Market News**:\n",
      "  - Sony raises profit forecast after earnings beat\n",
      "  - U.S. markets rally in anticipation of FOMC meeting outcomes\n",
      "  - European markets gain on strong manufacturing data\n",
      "\n",
      "The dashboard provides a clean, professional, and responsive layout suitable for financial analysis.\n"
     ]
    }
   ],
   "source": [
    "# Initialize aisuite client\n",
    "client = ai.Client()\n",
    "\n",
    "# Combine all available tools\n",
    "all_tools = fetch_mcp.get_callable_tools() + filesystem_mcp.get_callable_tools()\n",
    "\n",
    "print(\"📈 Fetching latest stock market data...\\n\")\n",
    "print(\"=\" * 60)\n",
    "\n",
    "# Create comprehensive research prompt\n",
    "response = client.chat.completions.create(\n",
    "    model=\"openai:gpt-4o\",\n",
    "    messages=[{\n",
    "        \"role\": \"user\",\n",
    "        \"content\": f\"\"\"Create a stock market movers dashboard for today ({datetime.now().strftime('%Y-%m-%d')}).\n",
    "\n",
    "**⚠️ CRITICAL EXECUTION RULES - READ FIRST:**\n",
    "1. DO NOT provide ANY text responses while executing tools\n",
    "2. DO NOT say things like \"Now let me...\", \"I'll create...\", or \"Let me gather...\"\n",
    "3. Execute ALL tools SILENTLY - fetch URLs, write files, etc.\n",
    "4. Your FIRST and ONLY text response must come AFTER the HTML file is successfully written\n",
    "5. If you respond with text before calling write_file, the tool execution loop will STOP and the file will NOT be created!\n",
    "\n",
    "**REMEMBER**: Research → Write HTML → THEN (and only then) respond with summary!\n",
    "\n",
    "---\n",
    "\n",
    "Steps to execute SILENTLY (no text responses until step 6):\n",
    "\n",
    "1. **Fetch latest market data** from these sources:\n",
    "   - Yahoo Finance market movers: https://finance.yahoo.com/markets/stocks/gainers/\n",
    "   - MarketWatch: https://www.marketwatch.com/\n",
    "   - Or any other reliable financial news source\n",
    "   \n",
    "   Extract:\n",
    "   - Top 3 stocks that rose today (gainers)\n",
    "   - For each stock: ticker symbol, company name, price, % change\n",
    "   - Major market indices (S&P 500, Dow, NASDAQ) if available\n",
    "   - Key market news/headlines\n",
    "\n",
    "2. **Create a beautiful HTML dashboard** with:\n",
    "   \n",
    "   **Header Section**:\n",
    "   - Title: \"Stock Market Movers - [Today's Date]\"\n",
    "   - Market sentiment indicator (bullish/bearish/neutral)\n",
    "   \n",
    "   **Top Gainers Section**:\n",
    "   - Table or cards showing:\n",
    "     * Company name and ticker\n",
    "     * Current price\n",
    "     * % change (in green)\n",
    "     * Brief reason for rise if known\n",
    "      \n",
    "   **Market News Section**:\n",
    "   - 3-5 key headlines impacting the market\n",
    "   \n",
    "   **Footer**:\n",
    "   - Data sources cited\n",
    "   - Timestamp\n",
    "   - Disclaimer: \"This is for informational purposes only, not financial advice\"\n",
    "\n",
    "4. **Styling requirements**:\n",
    "   - Professional financial dashboard aesthetic\n",
    "   - Color coding: GREEN for gains, RED for losses\n",
    "   - Clean table or card-based layout\n",
    "   - Responsive design\n",
    "   - Modern typography\n",
    "   - Use shadows and borders for visual separation.\n",
    " \n",
    "5. **SAVE HTML FILE (still no text response yet!)**:\n",
    "   - Use write_file to save as 'stock_market_dashboard.html'\n",
    "   - Wait for confirmation that write succeeded\n",
    "   \n",
    "6. **NOW you can respond with text** - provide a summary with:\n",
    "   - Confirmation that the HTML file was created\n",
    "   - Number of stocks analyzed\n",
    "   - Top 3 gainers with % changes\n",
    "   - Optionally, Top 3 losers with % changes\n",
    "   - Overall market sentiment\n",
    "\n",
    "Make it look like a professional Bloomberg/Yahoo Finance dashboard!\"\"\"\n",
    "    }],\n",
    "    tools=all_tools,\n",
    "    max_turns=30\n",
    ")\n",
    "\n",
    "print(\"\\n\" + \"=\" * 60)\n",
    "print(\"✓ STOCK MARKET DASHBOARD COMPLETE!\")\n",
    "print(\"=\" * 60)\n",
    "print(f\"\\n{response.choices[0].message.content}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Verify File Was Created"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ File created successfully!\n",
      "   - Filename: stock_market_dashboard.html\n",
      "   - Size: 4,231 bytes\n",
      "   - Location: /Users/rohit/fleet/leclerc/aisuite-prs/aisuite-main/aisuite/examples/agents/stock_market_dashboard.html\n"
     ]
    }
   ],
   "source": [
    "filename = \"stock_market_dashboard.html\"\n",
    "\n",
    "if os.path.exists(filename):\n",
    "    file_size = os.path.getsize(filename)\n",
    "    print(f\"✅ File created successfully!\")\n",
    "    print(f\"   - Filename: {filename}\")\n",
    "    print(f\"   - Size: {file_size:,} bytes\")\n",
    "    print(f\"   - Location: {os.path.abspath(filename)}\")\n",
    "else:\n",
    "    print(f\"❌ ERROR: File was not created!\")\n",
    "    print(f\"   Expected: {filename}\")\n",
    "    print(f\"\\n   The agent may have stopped before writing the file.\")\n",
    "    print(f\"   Try re-running with a higher max_turns value.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## View the Generated Dashboard"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "        <iframe\n",
       "            width=\"900\"\n",
       "            height=\"800\"\n",
       "            src=\"stock_market_dashboard.html\"\n",
       "            frameborder=\"0\"\n",
       "            allowfullscreen\n",
       "            \n",
       "        ></iframe>\n",
       "        "
      ],
      "text/plain": [
       "<IPython.lib.display.IFrame at 0x116915550>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "💡 Tip: Open 'stock_market_dashboard.html' in your browser for full-screen viewing!\n"
     ]
    }
   ],
   "source": [
    "from IPython.display import IFrame, display\n",
    "\n",
    "if os.path.exists(filename):\n",
    "    display(IFrame(src=filename, width=900, height=800))\n",
    "    print(f\"\\n💡 Tip: Open '{filename}' in your browser for full-screen viewing!\")\n",
    "else:\n",
    "    print(f\"⚠️  File not found: {filename}\")\n",
    "    print(\"The dashboard was not created. Check the error above.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Optional: View Tool Execution History\n",
    "\n",
    "See what sources the agent consulted and when it wrote the file:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tool Execution History:\n",
      "\n",
      "============================================================\n",
      "\n",
      "[1] 🌐 Fetched: https://finance.yahoo.com/markets/stocks/gainers/...\n",
      "\n",
      "[1] 🌐 Fetched: https://www.marketwatch.com/...\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "'dict' object has no attribute 'role'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[6], line 8\u001b[0m\n\u001b[1;32m      5\u001b[0m write_count \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[1;32m      7\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i, msg \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28menumerate\u001b[39m(response\u001b[38;5;241m.\u001b[39mchoices[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mintermediate_messages, \u001b[38;5;241m1\u001b[39m):\n\u001b[0;32m----> 8\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[43mmsg\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrole\u001b[49m \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124massistant\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(msg, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtool_calls\u001b[39m\u001b[38;5;124m'\u001b[39m) \u001b[38;5;129;01mand\u001b[39;00m msg\u001b[38;5;241m.\u001b[39mtool_calls:\n\u001b[1;32m      9\u001b[0m         \u001b[38;5;28;01mfor\u001b[39;00m tool_call \u001b[38;5;129;01min\u001b[39;00m msg\u001b[38;5;241m.\u001b[39mtool_calls:\n\u001b[1;32m     10\u001b[0m             \u001b[38;5;28;01mif\u001b[39;00m tool_call\u001b[38;5;241m.\u001b[39mfunction\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mfetch\u001b[39m\u001b[38;5;124m'\u001b[39m:\n",
      "\u001b[0;31mAttributeError\u001b[0m: 'dict' object has no attribute 'role'"
     ]
    }
   ],
   "source": [
    "print(\"Tool Execution History:\\n\")\n",
    "print(\"=\" * 60)\n",
    "\n",
    "fetch_count = 0\n",
    "write_count = 0\n",
    "\n",
    "for i, msg in enumerate(response.choices[0].intermediate_messages, 1):\n",
    "    if msg.role == \"assistant\" and hasattr(msg, 'tool_calls') and msg.tool_calls:\n",
    "        for tool_call in msg.tool_calls:\n",
    "            if tool_call.function.name == 'fetch':\n",
    "                fetch_count += 1\n",
    "                args = json.loads(tool_call.function.arguments)\n",
    "                url = args.get('url', 'N/A')\n",
    "                print(f\"\\n[{i}] 🌐 Fetched: {url[:80]}...\")\n",
    "            elif tool_call.function.name == 'write_file':\n",
    "                write_count += 1\n",
    "                args = json.loads(tool_call.function.arguments)\n",
    "                path = args.get('path', 'N/A')\n",
    "                content_size = len(args.get('contents', ''))\n",
    "                print(f\"\\n[{i}] 💾 WROTE FILE: {path} ({content_size:,} bytes)\")\n",
    "\n",
    "print(f\"\\n{'=' * 60}\")\n",
    "print(f\"Total web fetches: {fetch_count}\")\n",
    "print(f\"Total file writes: {write_count}\")\n",
    "\n",
    "if write_count == 0:\n",
    "    print(\"\\n⚠️  WARNING: No file writes detected!\")\n",
    "    print(\"   The agent did not call write_file.\")\n",
    "elif write_count == 1:\n",
    "    print(\"\\n✅ Perfect! File was written exactly once.\")\n",
    "else:\n",
    "    print(f\"\\n⚠️  NOTE: File was written {write_count} times (may have been overwritten)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Market Refresh\n",
    "\n",
    "Markets change throughout the day! Re-run the notebook to get fresh data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f\"Dashboard generated at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\")\n",
    "print(\"\\n💡 Tip: Re-run the 'Generate Market Movers Dashboard' cell for updated data!\")\n",
    "print(\"\\n⚠️  Disclaimer: This is for informational purposes only.\")\n",
    "print(\"   This is not financial advice. Always do your own research.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cleanup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Close MCP connections\n",
    "fetch_mcp.close()\n",
    "filesystem_mcp.close()\n",
    "\n",
    "print(\"✓ MCP servers closed\")\n",
    "if os.path.exists(filename):\n",
    "    print(f\"✓ Your dashboard is saved as: {filename}\")\n",
    "print(\"\\n📊 Happy trading! (Remember: not financial advice!)\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
